<?php
/**
 * 文件逻辑
 */
namespace Logic;
use Logic\CommonLogic;
class FileLogic extends CommonLogic {
    /**
     * 资源配置
     * @var array
     */
    private $resource_config = [];
    
    /**
     * 上传配置
     * @var array
     */
    private $upload_config = [];
    
    public function __construct() {
        parent::__construct();
        $this->resource_config = config('RESOURCE');
        
        $this->upload_config = config('UPLOAD');
        $this->upload_config['DIR'] = isset($this->upload_config['DIR']) ? rtrim($this->upload_config['DIR'], '/').'/' : ROOT_PATH . '/Upload/';        // 上传目录
    }
    
    /**
     * 文件上传
     * @param array $upload_data      文件数据信息
     * @return array
     */
    public function upload($upload_data){
        // 非分片上传
        if(!move_uploaded_file($upload_data['tmp_name'], $this->upload_config['DIR'].$upload_data['name'])){
            return $this->error(lang('UPLOAD_MOVE_ERROR'));
        }
        
        $upload_data['resource_path'] = $upload_data['name'];        // 资源路径
        
        // 上传成功
        $file_info = $this->_getUploadResult($upload_data);
        
        return $this->success($file_info);
    }
    
    /**
     * 文件分片上传
     * @param array $upload_data        上传数据
     * @param array $form_data          表单数据
     * @return array
     */
    public function chunkUpload($upload_data, $form_data){
        $file_guid = md5($form_data['fileName']);
        
        // 创建临时文件目录
	$tmp_file_path = $this->upload_config['DIR']."_".$file_guid;
	if(!is_dir($tmp_file_path)){
            if(!mkdir($tmp_file_path, 0777, true)){
                return $this->error(lang('UPLOAD_TPL_DIR_CREATE_ERROR'));
            }
	}
	
        // 临时文件块名称
	$tmp_file_name = $tmp_file_path."/".$form_data['currentChunk'].".blob";
        
        // 文件块是否存在
        if(file_exists($tmp_file_name)){
            $upload_success_data = [
                'chunk_index'   => $form_data['currentChunk']
            ];
            $upload_rs = $this->_getUploadResult($upload_success_data, 'chunk');
            return $this->success($upload_rs);
        }
        
        // 移动文件
	if(!move_uploaded_file($upload_data['tmp_name'], $tmp_file_name)){
            return $this->error(lang('UPLOAD_MOVE_ERROR'));
	}
        
	// 计算文件分块是是否等于总分块数
	$blob_file_list = scandir($tmp_file_path);		// 分块文件列表
	$dir_file_count = count($blob_file_list)-2;		// 块文件数量
        
	// 文件块数量达到总量时，投递文件合并任务
	if($dir_file_count == $form_data['totalChunk']){
            // 投递异步任务文件合并
            $file_full_name = $this->upload_config['DIR'].$form_data['fileName'];       // 文件全路径名
            Core()->server->task([
                'handle'    => 'Logic/File/chunkMerge'      // 任务处理函数
                ,'argv'     => [        // 处理函数参数
                    'tmp_file_path'=>$tmp_file_path,        // 零食文件块目录
                    'file_full_name'=>$file_full_name       // 合并生成文件名
                ]], -1, function($server, $task_id, $data){
                echo "---任务完成--";
                var_dump($data);
            });
	}
        
        $upload_success_data = [
            'chunk_index'   => $form_data['currentChunk']
        ];
        $upload_rs = $this->_getUploadResult($upload_success_data, 'chunk');
        return $this->success($upload_rs);
        
        
//        // 文件合成
//        $chunk_merge_rs = $this->_fileChunkMerge($tmp_file_path, $this->upload_config['DIR'].$form_data['fileName']);
//        if($chunk_merge_rs !== true){
//            return $this->error($chunk_merge_rs);
//        }
//        
//        $upload_success_data = [
//            'resource_path'   => $form_data['fileName']
//        ];
//        $upload_rs = $this->_getUploadResult($upload_success_data, 'file');
//        return $this->success($upload_rs);
    }
    
    /**
     * 文件块合成文件
     * @param array $argv       参数集
     * @param string $argv['tmp_file_path']     文件块目录
     * @param string $argv['file_full_name]    合并文件名
     * @return string|boolean
     */
    public function chunkMerge($argv){
        if(!isset($argv['tmp_file_path'])) return error(lang('TMP_FILE_PATH_ERROR'));
        if(!isset($argv['file_full_name'])) return error(lang('FILE_FULL_NAME_ERROR'));
        
        $tmp_file_path = $argv['tmp_file_path'];
        $file_full_name = $argv['file_full_name'];
        
        $blob_file_list = scandir($tmp_file_path);		// 分块文件列表
	$blob_count = count($blob_file_list)-2;		// 块文件数量
        
        // 全部上传完成,读取每个文件块并按顺序合并
        $file_merge_rs = null;
	for($i=0; $i<$blob_count; $i++){
            // 读取文件
            $blob_file_name = $tmp_file_path."/".$i.".blob";
            $blob_content = file_get_contents($blob_file_name);     // 读取块文件数据
            // 追加写入最终文件
            if(!file_put_contents($file_full_name, $blob_content, FILE_APPEND)){
                $file_merge_rs = false;
                break;
            }
            $file_merge_rs = true;
	}
        
        // 文件合并失败
        if($file_merge_rs !== true) return error(lang('UPLOAD_CHUNK_MERGE_ERROR'));
	
	// 删除临时文件及目录
	foreach($blob_file_list as $_t_f){
            if($_t_f == '.' || $_t_f == '..'){continue;}
            unlink($tmp_file_path."/".$_t_f);
	}
	rmdir($tmp_file_path);
        
        return success();
    }
    
    /**
     * 获取上传结果
     * @param array $upload_result 上传处理结果
     * @param string $type          类型；chunk:文件块、file:文件
     * @return array 
     */
    private function _getUploadResult($upload_result, $type='file'){
        $file_rs = ['type' => $type];
        
        if($type == 'file'){
            $file_rs['src'] = $this->resource_config['DOMAIN'] . '/' . $upload_result['resource_path'];
        }else if($type == 'chunk'){
            $file_rs['chunk_index'] = $upload_result['chunk_index'];        // 文件块索引
        }
        return $file_rs;
    }
}